package com.candoit.webapps.pricing.controllers;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.candoit.webapps.exceptions.SinConsumoPapelMesException;
import com.candoit.webapps.pricing.bean.adapters.IntegerAdapter;
import com.candoit.webapps.pricing.bean.adapters.MyLineaConverter;
import com.candoit.webapps.pricing.bean.adapters.MyTipoLineaConverter;
import com.candoit.webapps.pricing.bean.adapters.MyTipoPapelConverter;
import com.candoit.webapps.pricing.model.Articulo;
import com.candoit.webapps.pricing.model.Linea;
import com.candoit.webapps.pricing.model.MateriaPrima;
import com.candoit.webapps.pricing.model.TipoLinea;
import com.candoit.webapps.pricing.util.CostoRealUtil;
import com.candoit.webapps.pricing.util.QueryUtil;

@ManagedBean(name = "calculoCostosCtrl")
@SessionScoped
public class CalculoCostosController extends AbstractCostosMateriasPrimas {
	private IntegerAdapter integerAdapter;
	private MyLineaConverter lineaConverter;
	private MyTipoLineaConverter tipoLineaConverter;
	private MyTipoPapelConverter tipoPapelConverter;
	
	private List<Articulo> articulos = null;
	private Map<Articulo, List<CostoRealUtil>> mapaArticulos = null;
	private Linea lineaSelected = null;
	private List<Linea> listaLineas;
	private List<TipoLinea> tipoProductivoLista;
	private Boolean recalculable = true;
	private List<Linea> lineasSeleccionadas;
	private boolean isDataRendereable;
	private boolean existsNewRequestForView;
	private boolean tipoProductivoChanged;
	
	private List<CostoRealUtil> articulosFV;
	
	private Integer tipo;
 		
	public CalculoCostosController(){
		iniciarTipoProductivoLinea();
		iniciarNivelesLista();
		iniciarLineasDisponibles();
		iniciarPapelesDisponibles();
		mapaArticulos = new HashMap<Articulo, List<CostoRealUtil>>();
	}
	
	public boolean isDataRendereable() {
		return isDataRendereable;
	}

	public void setDataRendereable(boolean isDataRendereable) {
		this.isDataRendereable = isDataRendereable;
	}

	public void recargarTipoProductivo(){
		TipoLinea tl = getTipoProductivo();
	}
	
	public void iniciarPapelesDisponibles(){
		tipoPapelConverter = new MyTipoPapelConverter();
	}
	
	public MyTipoPapelConverter getTipoPapelConverter() {
		return tipoPapelConverter;
	}

	public void setTipoPapelConverter(MyTipoPapelConverter tipoPapelConverter) {
		this.tipoPapelConverter = tipoPapelConverter;
	}

	private void iniciarTipoProductivoLinea(){
		tipoLineaConverter = new MyTipoLineaConverter();
		tipoProductivoLista = new ArrayList<TipoLinea>();
		TipoLinea industrial = QueryUtil.getInstance().getTipoLineaById(TipoLinea.INDUSTRIAL);
		TipoLinea artesanal = QueryUtil.getInstance().getTipoLineaById(TipoLinea.ARTESANAL);
		tipoProductivoLista.add(industrial);
		tipoProductivoLista.add(artesanal);
	}
	
	private void iniciarLineasDisponibles(){
		lineaConverter = new MyLineaConverter();
	}
	
	public MyTipoLineaConverter getTipoLineaConverter() {
		return tipoLineaConverter;
	}

	@Override
	public void setTipoProductivo(TipoLinea tipoProductivo) {
		super.setTipoProductivo(tipoProductivo);
		this.tipoProductivoChanged=true;
	}
	
	public List<TipoLinea> getTipoProductivoLista() {
		return tipoProductivoLista;
	}
	
	public List<MateriaPrima> getPapelesLista(){
		if (getTipoProductivo().getId()==TipoLinea.INDUSTRIAL){
			return QueryUtil.getInstance().getMateriaPrimaByPapel(); 
		}else{
			return QueryUtil.getInstance().getMateriaPrimaByCartulina();
		}
	}

	public List<Linea> getLineasDisponibles() {
		if (getTipoProductivo().getId()==TipoLinea.INDUSTRIAL){
			return QueryUtil.getInstance().getLineasIndustriales();			
		}else{
			return QueryUtil.getInstance().getLineasArtesanales();
		}
	}

	private void iniciarNivelesLista(){
		integerAdapter = new IntegerAdapter();
	}
	
	public List<Integer> getNivelesLista() {
		List<Integer> nivelesLista = new ArrayList<Integer>();
		Integer cantNiveles;
		if (getTipoProductivo().getId()==TipoLinea.INDUSTRIAL){
			cantNiveles = 5;
		}else{
			cantNiveles = 2;
		}
		for(Integer i = 1; i <= cantNiveles ; i++){
			nivelesLista.add(i);
		}
		return nivelesLista;
	}

	public IntegerAdapter getIntegerAdapter() {
		return integerAdapter;
	}
	
	public MyLineaConverter getLineaConverter() {
		return lineaConverter;
	}

	public List<CostoRealUtil> listResumeCostos(Articulo articulo) throws SinConsumoPapelMesException{
		if (articulo != null){
			List<CostoRealUtil> result = new ArrayList<CostoRealUtil>();
			Iterator<MateriaPrima> it  = null;
			if (papeles == null || papeles.isEmpty()){
				List<MateriaPrima> list = getPapelesLista();
				it = list.iterator();
			}else{
				it = papeles.iterator();
			}
				while (it.hasNext()){
					MateriaPrima materia = (MateriaPrima) it.next();
					prepareCommandCost(result,articulo,materia);
				}
			
			return result;
		
		}else{
			return null;
		}
	}
	
	private void prepareCommandCost(List<CostoRealUtil> result, Articulo articulo, MateriaPrima materia) throws SinConsumoPapelMesException{
		DecimalFormat fourDForm = new DecimalFormat("#.####");
		CostoRealUtil util = new CostoRealUtil();
		util.setMateria(materia);

		Double costoMp = calcularCostoMPArticuloDolar(articulo, materia,false);
		Double scrap = costoMp * 0.10d;
		Double ArmadoMO = calcularArmadoDolar(articulo);
		costoMp = costoMp + scrap + ArmadoMO;
		Double costoDirecto = getCostoDirectoDolar(articulo, false);
		
		/*solo necesario en esta vista por el session scope*/
		if(tipoProductivoChanged){
			saveCalculoInternoSinAsignar(false);
			saveCalculoInternoSinAsignar(true);
			saveCalculoInternoSalarioSinAsignar(false);
			saveCalculoInternoSalarioSinAsignar(true);
			tipoProductivoChanged = false;
		}
		
		Double costoIndirecto = getCostoIndirectoDolar(articulo.getFormato().getLinea(),false);
		Double costoSalario = getCostoSalariosDolar(articulo,false);
		Double costoReal= costoMp + costoDirecto + costoIndirecto + costoSalario;
		Double rentabilidad= 0.00d;
		if (articulo.getFormato() != null){
			rentabilidad = articulo.getFormato().getRentabilidad();
		}
		Double precioReal = calcularPrecio(costoReal, rentabilidad);
		
		util.setPorcentajeReal( precioReal);
		util.setCostoReal(fourDForm.format(costoReal));
		
		Double costoMpSim = calcularCostoMPArticuloDolar(articulo, materia,true);
		Double scrapSim = costoMpSim * 0.10d;
		costoMpSim = costoMpSim + scrapSim + ArmadoMO;
		Double costoDirectoSim = getCostoDirectoDolar(articulo, true);
		Double costoIndirectoSim = getCostoIndirectoDolar(articulo.getFormato().getLinea(),true);
		Double costoSalarioSim = getCostoSalariosDolar(articulo,true);
		Double costoSim = costoMpSim + costoDirectoSim + costoIndirectoSim + costoSalarioSim;
		Double precioSim = calcularPrecio(costoSim, rentabilidad);
		
		util.setCostoSimulado(costoSim);
		util.setPorcentajeSimulado(precioSim);
		util.setArticulo(articulo);
		
		result.add(util);
	}

	private Double calcularPrecio(Double costo, Double rentabilidad){
		return costo * (1 + rentabilidad/100);
	}
	
	private List<CostoRealUtil> initArticulosForView(){
		List<CostoRealUtil> arts = new ArrayList<CostoRealUtil>();
		for(Articulo a : getArticulos()){
			List<CostoRealUtil> laux =  summaryCostList(a);
			if(laux != null){
				for(CostoRealUtil cru : laux){
					arts.add(cru);
				}
			}
		}
		return arts;
	}
	
	public List<CostoRealUtil> getArticulosFV() {
		if(articulosFV == null || articulosFV.isEmpty() || existsNewRequestForView){
			if(existsNewRequestForView){
				existsNewRequestForView=false;
				articulosFV = initArticulosForView();
			}else{
				articulosFV = new ArrayList<CostoRealUtil>();
			}
		}
		return articulosFV;
	}

	public void setArticulosFV(List<CostoRealUtil> articulosFV) {
		this.articulosFV = articulosFV;
	}

	public List<Articulo> getArticulos() {
		if (lineasSeleccionadas == null || lineasSeleccionadas.isEmpty()){
			/*debe traer todos los articulos*/
			articulos = QueryUtil.getInstance().getArticulosByTipoLinea(getTipoProductivo());
		}else{
			articulos = QueryUtil.getInstance().getArticulosByLineas(lineasSeleccionadas);
		}
		
		return articulos;
	}

	public void setArticulos(List<Articulo> articulos) {
		this.articulos = articulos;
	}

	public List<Linea> getListaLineas() {
		if (lineaSelected == null){
			listaLineas = QueryUtil.getInstance().getLineas();
		}else{
			listaLineas = new ArrayList<Linea>();
			listaLineas.add(lineaSelected);
		}
		return listaLineas;
	}
		
	public void buscarArticulos() throws SinConsumoPapelMesException{
		initCalculoCostos();
		//TODO: las 4 variables de abajo solo son para control, se pueden eliminar
		TipoLinea ttl = getTipoProductivo();
		Integer tnp = getNivelDelNivelProductivo();
		List<Linea> tls = getLineasSeleccionadas();
		List<MateriaPrima> tps = getPapeles();
		
		mapaArticulos = new HashMap<Articulo, List<CostoRealUtil>>();
		for (Articulo a :getArticulos()){
			List<CostoRealUtil> auxList = null;
			try {
				auxList = listResumeCostos(a);
			} catch (SinConsumoPapelMesException e) {
				// TODO ver si conviene mostrar unmensaje
				e.printStackTrace();
			}
			mapaArticulos.put(a, auxList);
		}
		for(Articulo a : articulos){
		List<CostoRealUtil> auxList = listResumeCostos(a);
		mapaArticulos.put(a, auxList);
		}
		
		isDataRendereable = true;
		existsNewRequestForView = true;
	}
	
	public List<CostoRealUtil> summaryCostList(Articulo articulo){
		try {
			return mapaArticulos.get(articulo);
		} catch (Exception e) {
			return new ArrayList<CostoRealUtil>();
		}
	}

	public Boolean getRecalculable() {
		return recalculable;
	}

	public void setRecalculable(Boolean recalculable) {
		this.recalculable = recalculable;
	}
	public List<Linea> getLineasSeleccionadas() {
		return lineasSeleccionadas;
	}
	
	public void setLineasSeleccionadas(List<Linea> lineasSeleccionadas) {
		this.lineasSeleccionadas = lineasSeleccionadas;
	}

	@Override
	public TipoLinea getTipoProductivo() {
		if (super.getTipoProductivo() == null){
			if(this.lineasSeleccionadas != null){
				this.lineasSeleccionadas=this.lineasSeleccionadas;
			}else if(this.papeles != null){
				this.papeles=this.papeles;
			}else{
				this.tipoProductivo = QueryUtil.getInstance().getTipoLineaById(TipoLinea.INDUSTRIAL);
			}
			this.tipoProductivo = QueryUtil.getInstance().getTipoLineaById(TipoLinea.INDUSTRIAL);
		} 
		return this.tipoProductivo;
	}
	
}
